package de.breitbeil.jbooking.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Property;
import org.hibernate.impl.SessionImpl;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

// http://www.tutorials.de/forum/enterprise-java-jee-j2ee-spring-co/283835-strukturierung-webanwendung.html
public class GenericDao extends HibernateDaoSupport implements IGenericDao {

    @SuppressWarnings("unchecked")
    public <TEntity> List<TEntity> findAll(final Class<TEntity> entityClass) {
        return getHibernateTemplate().loadAll(entityClass);
    }

    @SuppressWarnings("unchecked")
    public <TEntity> List<TEntity> findByAttribute(
            final Class<TEntity> entityClass, final String attributeName,
            final Object attributeValue) {
        
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                return session.createCriteria(entityClass).add(
                        Property.forName(attributeName).eq(attributeValue))
                        .list();
            }
        });
    }

    @SuppressWarnings("unchecked")
    public <TEntity> List<TEntity> findByAttributes(
            final Class<TEntity> entityClass, final List<String> attributeNames,
            final List<Object> attributeValues) {
        
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(entityClass);
                for (int i = 0; i < attributeNames.size(); i++) {
                    criteria.add(Property.forName(attributeNames.get(i)).eq(
                            attributeValues.get(i)));
                }
                return criteria.list();
            }
        });
    }

    @SuppressWarnings("unchecked")
    public <TEntity, TKey extends Serializable> TEntity getBy(
            Class<TEntity> entityClass, TKey key) {
        return (TEntity) getHibernateTemplate().get(entityClass, key);
    }

    @SuppressWarnings("unchecked")
    public void makePersistent(Object entity) {
        getHibernateTemplate().saveOrUpdate(entity);
    }

    public void makeTransient(final Object entity) {
        getHibernateTemplate().delete(entity);
    }

}
